﻿using QuanLyGiaoVuDAL.DTO;
using QuanLyGiaoVuService.CommandServices;
using QuanLyGiaoVuService.CommonServices;
using QuanLyGiaoVuService.Domain;
using QuanLyGiaoVuService.ReportServices;
using QuanLyGiaoVuService.Utilities;
using QuanLyGiaoVuUI.Extensions.ExtendedAttributes;
using QuanLyGiaoVuUI.Extensions.Utilities;
using QuanLyGiaoVuUI.Models.LopMonHoc;
using QuanLyGiaoVuUI.Models.QuanLySinhVien;
using QuanLyGiaoVuUI.Models.SinhVien;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace QuanLyGiaoVuUI.Controllers
{
    [GiangVienAuthorize(ChiGiaoVu=true)]
    [HandleError]
    public class QuanLySinhVienController : Controller
    {
        private ISinhVienReportService _sinhVienReportService;
        private ISinhVienCommandService _sinhVienCommandService;
        private ILopMonHocReportService _lopMonHocReportService;
        private ITaiLieuReportService _taiLieuReportService;
        private IFileService _fileService;
        private IThamSoService _thamSoService;
        private IExcelService _excelService;
        private IHocKyReportService _hocKyReportService;

        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public QuanLySinhVienController(ISinhVienReportService sinhVienReportService, ISinhVienCommandService sinhVienCommandService, IFileService fileService, IThamSoService thamSoService, IExcelService excelService, ILopMonHocReportService lopMonHocReportService, ITaiLieuReportService taiLieuReportService, IHocKyReportService hocKyReportService)
        {
            _sinhVienReportService = sinhVienReportService;
            _sinhVienCommandService = sinhVienCommandService;
            _fileService = fileService;
            _thamSoService = thamSoService;
            _excelService = excelService;
            _lopMonHocReportService = lopMonHocReportService;
            _taiLieuReportService = taiLieuReportService;
            _hocKyReportService = hocKyReportService;
        }

        [HttpGet]
        public ActionResult Index()
        {
            var viewModel = _lopMonHocReportService.GetAllLopSinhVien().OrderBy(lop => lop.KhoaNam);
            return View(viewModel);
        }

        [HttpGet]
        public ActionResult DanhSachSinhVien(Guid? maLopSinhVien)
        {
            IEnumerable<SinhVienViewModel> dsSinhVien = SinhVienViewModel.FromSinhVienDTOList(_sinhVienReportService.GetAllSinhVien(maLopSinhVien, null));
            return View(dsSinhVien);
        }
        [HttpGet]
        public ActionResult CapNhatThongTinSinhVien(Guid svid)
        {
            SinhVienViewModel sv = SinhVienViewModel.FromSinhVienDTO(_sinhVienReportService.GetSinhVienById(svid));
            return View(sv);
        }

        [HttpPost]
        public ActionResult CapNhatSinhVien(Guid svid,
            string masv,
            string hotensv,
            string gioitinhsv,
            string ngaysinh,
            string quequansv,
            string diachisv,
            string emailsv)
        {
            bool isSuccess = true;
            String mess = "Cập nhật thành công!";
            if (masv == null || masv == "")
            {
                isSuccess = false;
                mess = "Mã sinh viên không được rỗng!";
                return Json(new { success = isSuccess, message = mess });
            }
            if (hotensv == null || hotensv == "")
            {
                isSuccess = false;
                mess = "Họ tên sinh viên không được rỗng!";
                return Json(new { success = isSuccess, message = mess });
            }
            DateTime ngaysinhsv=new DateTime();
            bool ischange = false;
            try{
                ngaysinhsv = DateTime.Parse(ngaysinh);
                ischange = true;
            }catch(Exception e){
                isSuccess = false;
                mess = "Sai định dạng ngày sinh sinh viên!(Định dạng đúng là: mm/dd/yyyy)";
                return Json(new { success = isSuccess, message = mess });
            }
           SinhVienDTO sv= _sinhVienReportService.GetSinhVienById(svid);
            sv.MaSinhVien = masv;
            sv.HoTenSV = hotensv;
            sv.GioiTinh = (gioitinhsv == "0" ? 0 : 1);
            if (ischange)
            {
                sv.NgaySinh = ngaysinhsv;
            }
            sv.QueQuan = quequansv;
            sv.DiaChi = diachisv;
            sv.Email = emailsv;

            if (_sinhVienCommandService.UpdateSinhVien(sv)==null)
            {
            }
            return Json(new { success = isSuccess, message = mess });
        }

        [HttpGet]
        public ActionResult DanhSachDieuKienLuanVan(Guid? maLopSinhVien)
        {
            IEnumerable<SinhVienViewModel> dsSinhVien = SinhVienViewModel.FromSinhVienDTOList(_sinhVienReportService.GetAllSinhVien(maLopSinhVien, null));
            return View(dsSinhVien);
        }

        [HttpGet]
        public ActionResult NhapDanhSachSinhVienDialog()
        {
            NhapDanhSachSinhVienViewModel viewModel = new NhapDanhSachSinhVienViewModel();
            viewModel.danhSachFileMau = _taiLieuReportService.GetAllTaiLieu(UserUtility.GetCurrentUser().MaNguoiDung, true, _thamSoService.GetGuid(ThamSoConstantUtility.MALOAIFILEMAU), null, null);
            return View(viewModel);
        }

        [HttpPost]
        public JsonResult NhapDanhSachSinhVien(Guid? FileMau)
        {
            bool success = true;
            try
            {
                Stream fileStream;
                string fileName, contentType;
                if (!FileMau.HasValue)
                    throw new Exception("Chưa chọn file mẫu.");
                bool readSuccess = _fileService.GetFileStreamById((Guid)FileMau, out fileStream, out fileName, out contentType);
                MemoryStream ms = new MemoryStream();
                byte[] buffer = new byte[4096];
                while (true)
                {
                    int readDataCount = fileStream.Read(buffer, 0, buffer.Length);
                    if (readDataCount <= 0)
                        break;
                    ms.Write(buffer, 0, readDataCount);
                }
                fileStream.Close();

                var templateTokenList = _excelService.GetAllTokenFromTemplate(ThamSoConstantUtility.SINHVIENTEMPLATE);
                uint startRowIndex;
                var templateInfo = _excelService.GetInfoFromTemplateFile(ms, templateTokenList, out startRowIndex);

                ms = new MemoryStream();
                Stream inputStream = Request.Files.Count > 0 ? Request.Files[0].InputStream : null;
                if (inputStream == null)
                    throw new Exception("Tải file dữ liệu không thành công.");
                buffer = new byte[4096];
                while (true)
                {
                    int readDataCount = inputStream.Read(buffer, 0, buffer.Length);
                    if (readDataCount <= 0)
                        break;
                    ms.Write(buffer, 0, readDataCount);
                }
                inputStream.Close();

                var dsSinhVien = SinhVienTemplateModel.ToSinhVienDTOList(_excelService.ReadExcelDataFile<SinhVienTemplateModel>(ms, templateTokenList.ToList(), (int)startRowIndex));
                success = _sinhVienCommandService.InsertOrUpdateSinhVienByList(dsSinhVien);
                if (success)
                    return Json(new
                    {
                        success = true
                    });
                else
                    return Json(new
                    {
                        success = false,
                        message = "Cập nhật sinh viên không thành công."
                    });
            }
            catch (Exception exception)
            {
                return Json(new
                {
                    success = false,
                    message = exception.Message
                });
            }
        }

        [HttpGet]
        public ActionResult DieuKienLuanVan()
        {
            var viewModel = _lopMonHocReportService.GetAllLopSinhVien().OrderBy(lop => lop.KhoaNam);
            return View(viewModel);
        }

        [HttpGet]
        public ActionResult NhapDieuKienLuanVanTuFile()
        {
            var viewModel = new NhapDieuKienLuanVanViewModel();
            return View(viewModel);
        }

        [HttpPost]
        public JsonResult NhapDieuKienLuanVanTuFile(NhapDieuKienLuanVanViewModel viewModel)
        {
            try
            {
                Stream fileStream;
                string fileName, contentType;
                _fileService.GetFileStreamById(viewModel.MaTapTin, out fileStream, out fileName, out contentType);
                MemoryStream ms = new MemoryStream();
                byte[] buffer = new byte[4096];
                while (true)
                {
                    int readCount = fileStream.Read(buffer, 0, buffer.Length);
                    if (readCount <= 0)
                        break;
                    ms.Write(buffer, 0, readCount);
                }
                fileStream.Close();

                IEnumerable<ExcelReadDataModel> data = _excelService.ReadExcelDataFile(ms, viewModel.StartRowIndex, viewModel.EndRowIndex, viewModel.IdentityColumnIndex, viewModel.ValueColumnIndex);
                _sinhVienCommandService.UpdateDKLuanVan(data);
                return Json(new
                {
                    success = true
                });
            }
            catch (Exception exception)
            {
                log.Error(exception.Message, exception);
                return Json(new { 
                    success = false,
                    message = "Không thể đọc dữ liệu từ file."
                });
            }
        }

        [HttpPost]
        [GiangVienAuthorize(ChiGiaoVu=false, ReturnJson=true)]
        public JsonResult UpLoadFile()
        {
            object jsonData;
            HttpPostedFileBase file = Request.Files[0];

            if (ModelState.IsValid && file != null)
            {
                Guid maTapTinCu = _thamSoService.GetGuid(ThamSoConstantUtility.TAPTINTAM);
                if (maTapTinCu != Guid.Empty)
                    _fileService.DeleteFileById(maTapTinCu);
                Guid maTapTin = Guid.Empty;
                _fileService.SaveFileFromStream(null, file.InputStream, file.FileName, file.ContentType, out maTapTin);
                _thamSoService.SetThamSo(ThamSoConstantUtility.TAPTINTAM, maTapTin.ToString());
                jsonData = new
                {
                    success = true,
                    fileName = file.FileName,
                    fileSize = file.ContentLength,
                    fileId = maTapTin
                };
            }
            else jsonData = new
            {
                success = false,
                message = "Upload file không thành công!"
            };
            return Json(jsonData); 
        }

        [HttpGet]
        public ActionResult NhapBangDiem()
        {
            return View();
        }

        [HttpGet]
        [ChildActionOnly]
        [GiangVienAuthorize(ChiGiaoVu=false)]
        public ActionResult NhapBangDiemDialog(Guid? maGiangVien)
        {
            NhapBangDiemViewModel viewModel = new NhapBangDiemViewModel();
            if (maGiangVien.HasValue)
                viewModel.MaGiangVien = maGiangVien.Value;
            viewModel.StartRowIndex = _thamSoService.GetInt(ThamSoConstantUtility.NHAPDIEMDONGBATDAU);
            viewModel.EndRowIndex = _thamSoService.GetInt(ThamSoConstantUtility.NHAPDIEMDONGKETTHUC);
            viewModel.IdentityColumnIndex = _thamSoService.GetThamSo(ThamSoConstantUtility.NHAPDIEMCOTMASOSINHVIEN);
            viewModel.ValueColumnIndex = _thamSoService.GetThamSo(ThamSoConstantUtility.NHAPDIEMCOTDIEMHOCPHAN);
            viewModel.MaHocKy = _thamSoService.GetGuid(ThamSoConstantUtility.HOCKYHIENTAI);
            viewModel.DanhSachLopSinhVien = _lopMonHocReportService.GetAllLopSinhVien().OrderBy(lop => lop.KhoaNam);
            viewModel.DanhSachHocKy = _hocKyReportService.GetAllHocKy().OrderBy(hk => hk.TenHocKy).OrderBy(hk => hk.NamHoc.Nam1);
            return View(viewModel);
        }

        [HttpPost]
        [GiangVienAuthorize(ChiGiaoVu=false, ReturnJson=true)]
        public JsonResult NhapBangDiemDialog(NhapBangDiemViewModel viewModel)
        {
            try
            {
                Stream fileStream;
                string fileName, contentType;
                _fileService.GetFileStreamById(viewModel.MaTapTin, out fileStream, out fileName, out contentType);
                MemoryStream ms = new MemoryStream();
                byte[] buffer = new byte[4096];
                while (true)
                {
                    int readCount = fileStream.Read(buffer, 0, buffer.Length);
                    if (readCount <= 0)
                        break;
                    ms.Write(buffer, 0, readCount);
                }
                fileStream.Close();

                IEnumerable<ExcelReadDataModel> data = _excelService.ReadExcelDataFile(ms, viewModel.StartRowIndex, viewModel.EndRowIndex, viewModel.IdentityColumnIndex, viewModel.ValueColumnIndex);
                var lopMonHoc = _lopMonHocReportService.GetLopMonHocById(viewModel.MaLopMonHoc);
                _sinhVienCommandService.NhapDiem(data, viewModel.MaHocKy, lopMonHoc.MaMonHoc);
                return Json(new
                {
                    success = true
                });
            }
            catch (Exception exception)
            {
                log.Error(exception.Message, exception);
                return Json(new
                {
                    success = false,
                    message = "Không thể đọc dữ liệu từ file."
                });
            }
            return Json(new object());
        }

        [HttpGet]
        [GiangVienAuthorize(ChiGiaoVu=false)]
        public ActionResult DanhSachLopMonHoc(Guid? maLopSinhVien, Guid? maHocKy, Guid? maGiangVien)
        {
            IEnumerable<LopMonHocViewModel> lopMonHocList = new List<LopMonHocViewModel>();
            if (maLopSinhVien.HasValue && maHocKy.HasValue)
            {
                if (maGiangVien.HasValue && maGiangVien.Value != Guid.Empty)
                {
                    lopMonHocList = LopMonHocViewModel.FromLopMonHocDTOList(_lopMonHocReportService.GetAllLopMonHocTheoGiangVienTrongHocKy(maGiangVien.Value, maHocKy.Value, true, true, true).Where(lop => lop.LopSinhVienId == maLopSinhVien.Value));
                }
                else
                {
                    lopMonHocList = LopMonHocViewModel.FromLopMonHocDTOList(_lopMonHocReportService.GetAllLopMonHocTheoHocKy(maHocKy.Value, null, null, null).Where(lop => lop.LopSinhVienId == maLopSinhVien.Value));
                }
            }
            return View(lopMonHocList);
        }

        [HttpPost]
        public ActionResult DoiTrangThaiDieuKienLuanVan(Guid? sinhVienId, bool? duDK)
        {
            try
            {
                if (sinhVienId.HasValue && duDK.HasValue)
                {
                    var sinhVien = _sinhVienReportService.GetSinhVienById(sinhVienId.Value);
                    if (sinhVien != null)
                    {
                        sinhVien.DuDKLuanVan = duDK.Value;
                        _sinhVienCommandService.UpdateSinhVien(sinhVien);
                    }
                    return Json(new
                    {
                        success = true
                    });
                }
                else
                {
                    return Json(new
                    {
                        success = false,
                        message = "Cập nhật không thành công."
                    });
                }
            }
            catch (Exception exception)
            {
                log.Error(exception.Message, exception);
                return Json(new { 
                    success = false,
                    message = "Cập nhật không thành công."
                });
            }
        }

    }
}
